package guda.mrpc.core.transport.callback;

import guda.mrpc.core.RpcRequest;
import guda.mrpc.core.server.ServiceProviderContainer;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.Callable;

/**
 * Created by well on 17/5/23.
 */
public abstract class ResponseCallback<T> implements Callable<T> {

    public static final Logger log = LoggerFactory.getLogger(ResponseCallback.class);

    protected ServiceProviderContainer serviceProviderContainer;

    protected RpcRequest request;
    protected ChannelHandlerContext ctx;

    public ResponseCallback(ChannelHandlerContext ctx,RpcRequest request, ServiceProviderContainer serviceProviderContainer) {
        this.request = request;
        this.ctx = ctx;
        this.serviceProviderContainer = serviceProviderContainer;
    }

    public abstract T call() throws Exception;


    protected Object handle(RpcRequest request) throws Throwable {


        String requestKey = request.getRequestKey().toString();
        Object serviceBean = serviceProviderContainer.lookupService(requestKey);

        if (null == serviceBean) {
            throw new RuntimeException("not found service [" + requestKey + "]");
        }

        Class<?> serviceClass = serviceBean.getClass();
        String methodName = request.getMethodName();
        Class<?>[] parameterTypes = request.getParameterTypes();
        Object[] parameters = request.getParameters();

        Method declaredMethod = serviceClass.getDeclaredMethod(methodName, parameterTypes);

        if(declaredMethod == null){
            throw new RuntimeException("not found service method [" + requestKey + "],method:["+methodName+"]");
        }
        return declaredMethod.invoke(serviceBean,parameters);

    }
}
